#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "i2c.h"

void I2C_setbitrate(unsigned int bitrate)
{

	unsigned char bitrate_div;
	bitrate_div = ((F_CPU/1000l)/bitrate);
	if(bitrate_div >= 16)
		bitrate_div = (bitrate_div-16)/2;
	TWBR = bitrate_div;
}

unsigned char I2C_start(void)
{
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
	
	if((TWSR&0xF8) != I2C_START) return 0;//START=0x08;repeated Start=0x10
	
	return 1;	
}

unsigned char I2C_sendbyte(unsigned char i2c_address,unsigned int i2c_memaddr,unsigned char i2c_data)
{
	unsigned char lower_address,upper_address;
	
	TWDR = (i2c_address<<1)&0xFE;
	//TWDR = (i2c_address)&0xFE;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
	
	if((TWSR&0xF8)!=I2C_MT_SLA_ACK) return 0;
	
	/*memory address*/
	//calculate lower_address
	lower_address = i2c_memaddr&0xff;
	//calculate upper_address
	upper_address = (i2c_memaddr>>8)&0xff;
	TWDR = upper_address;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
		
	if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	TWDR = lower_address;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
		
	if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	/*END OF memory address*/
	
	TWDR = i2c_data;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
	
	if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	return 1;
}

void I2C_stop(void)
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

unsigned char I2C_write(unsigned char i2c_address,unsigned int i2c_memaddr,unsigned i2c_data)
{
	I2C_start();
	I2C_sendbyte(i2c_address,i2c_memaddr,i2c_data);
	I2C_stop();
	return 1;
}

unsigned char I2C_receivebyte(unsigned char i2c_address, unsigned int i2c_memaddr)
{
	unsigned char upper_address,lower_address;
	unsigned char i2c_data=0;
	
	TWDR = (i2c_address<<1)&0xFE;
	//TWDR = (i2c_address)&0xFE;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));

	if((TWSR&0xF8)!=I2C_MT_SLA_ACK) return 0;
	
	/*memory address*/
	//calculate lower_address
	lower_address = i2c_memaddr&0xff;
	//calculate upper_address
	upper_address = (i2c_memaddr>>8)&0xff;
	TWDR = upper_address;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
		
	if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	TWDR = lower_address;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
		
	if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	
	/*END OF memory address*/
	
	I2C_start();
	
	TWDR = (i2c_address<<1)|0x01;
	//TWDR = (i2c_address)|0x01;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
	
	//if((TWSR&0xF8)!=I2C_MT_SLA_ACK) return 0;
	
	
	TWCR = (1<<TWINT)|(1<<TWEN);
	
	while(!(TWCR&(1<<TWINT)));
	i2c_data = TWDR ;
	//if((TWSR&0xF8) != I2C_MT_DATA_ACK) return 0;
	
	return i2c_data;
}

unsigned char I2C_read(unsigned char i2c_address,unsigned int i2c_memaddr)
{
	unsigned char temp;
	I2C_start();
	temp = I2C_receivebyte(i2c_address,i2c_memaddr);
	I2C_stop();
	return temp;
}